﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.Runtime.Serialization;
using System.ServiceModel;
using System.ServiceModel.Web;
using System.Text;
using System.Text.RegularExpressions;
using System.Web.Configuration;

namespace PhoneNumberFind
{
    /// <summary>
    /// Helper class that wraps a regular expression with the capability to
    /// scan a stream for matches.
    /// </summary>
    class StreamMatcher
    {
        /// <summary>
        /// The regex to use in searching the stream
        /// </summary>
        private Regex regex = null;

        /// <summary>
        /// Create a new StreamMatcher that will search the given pattern.
        /// </summary>
        /// <param name="pattern">The pattern to compile into a regular expression</param>
        /// <param name="options">Regular expression options</param>
        public StreamMatcher(string pattern, RegexOptions options)
        {
            // initialize the regular expression with the given pattern
            this.regex = new Regex(pattern, options);
        }

        private IEnumerable<string> GetLineMatches(string line)
        {
            // Yield all the matches found in the line to the set of results
            foreach (Match match in this.regex.Matches(line))
            {
                yield return match.Value;
            }
        }

        /// <summary>
        /// Scan the given stream for pattern matches.
        /// </summary>
        /// <param name="stream">The stream to scan</param>
        /// <returns>An array containing all matches of the given pattern</returns>
        public IEnumerable<string> GetMatches(Stream stream)
        {
            // Create a reader for the stream
            StreamReader reader = new StreamReader(stream);
            // Read the text line by line and search form matches
            // Avoid reading the entire response in case the response is large
            while (reader.Peek() != -1)
            {
                // Read the next line
                string line = reader.ReadLine();
                foreach (string match in this.GetLineMatches(line))
                {
                    yield return match;
                }
            }
        }
    }

    public class PhoneNumberFind : IPhoneNumberFind
    {
        /// <summary>
        /// Fetch the URL and return a readable stream containing the results.
        /// </summary>
        /// <param name="url">The URL to fetch</param>
        /// <returns>A readable stream containing the fetched response</returns>
        private static Stream GetURLAsStream(string url)
        {
            // Create a request to fetch the URL
            WebRequest request = WebRequest.Create(url);
            // Execute the request
            WebResponse response = request.GetResponse();
            // Return the data stream for the response
            return response.GetResponseStream();
        }

        public string[] FindPhoneNumbers(string url)
        {
            Stream stream = GetURLAsStream(url);
            string phoneNumberPattern = WebConfigurationManager.AppSettings["phonenumber.regex.text"];
            StreamMatcher matcher = new StreamMatcher(phoneNumberPattern, RegexOptions.IgnoreCase);
            HashSet<string> matches = new HashSet<string>(matcher.GetMatches(stream));
            return matches.ToArray();
        }
    }
}
